package com.itheima.stock.servier.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.generator.CodeGenerator;
import com.itheima.stock.constant.StockConstant;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.pojo.entity.SysUser;
import com.itheima.stock.servier.UserService;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.vo.req.LoginReqVo;
import com.itheima.stock.vo.resp.LoginRespVo;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * @param userName
     * @return 根据用户名返回用户信息
     */
    @Override
    public SysUser findByUserName(String userName) {
        return sysUserMapper.findUserInfoByUserName(userName);
    }

    /**
     * 用户登录
     *
     * @param loginReqVo
     * @return isBlank /--org.apache.commons.lang3.StringUtils;
     */
    @Override
    public R<LoginRespVo> login(LoginReqVo loginReqVo) {
        //1.判断入参合法
        if (loginReqVo == null || StringUtils.isBlank(loginReqVo.getUsername()) ||
                StringUtils.isBlank(loginReqVo.getPassword()) ) {
            return R.error(ResponseCode.DATA_ERROR);
        }

        //判断验证码
        if(StringUtils.isBlank(loginReqVo.getSessionId() )|| StringUtils.isBlank(loginReqVo.getCode())){

            return R.error(ResponseCode. CHECK_CODE_ERROR);
        }
          //判断redis中保存的验证码与输入的验证码是否相同（比较时忽略大小写校验验证码
        String redisCode = (String)redisTemplate.opsForValue().get(StockConstant.CHECK_PREFIX+loginReqVo.getSessionId());
        if (StringUtils.isBlank(redisCode)) {
            return R.error(ResponseCode.CHECK_CODE_TIMEOUT);
        }
        //比对
        if (!redisCode.equalsIgnoreCase(loginReqVo.getCode())) {
            return R.error(ResponseCode.CHECK_CODE_ERROR);
        }

        //2.去数据库查询用户信息，获取密码密文
        SysUser dbUser = sysUserMapper.findUserInfoByUserName(loginReqVo.getUsername());
        if (dbUser == null) {
            //用户不存在
            return R.error(ResponseCode.ACCOUNT_NOT_EXISTS);
        }

        //3.调用密码匹配器输入的明文密码和数据库的密码 先明文载密文
        // todo  passwordEncoder.encode(loginReqVo.getPassword()) 把传入原文加密

        if (!passwordEncoder.matches(loginReqVo.getPassword(),
                dbUser.getPassword())) {
            return R.error(ResponseCode.USERNAME_OR_PASSWORD_ERROR);
        }

        //4.响应
        LoginRespVo respVo = new LoginRespVo();
//        respVo.setUsername(userInfoByUserName.getUsername());
//        respVo.setNickName(userInfoByUserName.getNickName());
//        respVo.setPhone(userInfoByUserName.getPhone());
//        respVo.setId(userInfoByUserName.getId());

        //发现LoginRespVo与SysUser对象属性名称和类型一致
        //须保证属性名称和类型一致
        BeanUtils.copyProperties(dbUser, respVo);
        return R.ok(respVo);
    }

    /**
     * 生成验证码图片
     *
     * @return
     */
    @Override
    public R<Map> getCaptchaCode() {

        //1.生成图片验证码
        /**
         * 参数1：图片的宽度
         * 参数2：图片高度
         * 参数3：图片中包含验证码的长度
         * 参数4：干扰线数量
         */
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(250, 40, 4, 5);
        //设置背景色
        captcha.setBackground(Color.LIGHT_GRAY);
        //自定义校验规则
//        captcha.setGenerator(new CodeGenerator() {
//            @Override
//            public String generate() {
//                return null;
//                //自定义校验码逻辑
//            }
//
//            @Override
//            public boolean verify(String s, String s1) {
//                //匹配校验码逻辑
//                return false;
//            }
//        });

        //获取校验码
        String captchaCode = captcha.getCode();
        //获取经过base64编码处理的图片数据
        String imageData = captcha.getImageBase64();

        //2.生成sessionId  long => string 转化成string，避免前端精度丢失
        String sessionId = String.valueOf(idWorker.nextId());
        log.info("当前生成的图片校验码：{};会话id:{}", captchaCode, sessionId);
        //3. 将sessinId作为key，校验码作为vaLue保存在redis中
        /**
         * TimeUnit.MINUTES 分钟
         * 更用redis模拟sessioin的行为通过过期时间设置
         * KC加前缀，方便统计查看所有使用验证码的数量
         */
        redisTemplate.opsForValue().set(StockConstant.CHECK_PREFIX + sessionId, captchaCode, 5, TimeUnit.MINUTES);

        //4.组装数据
        Map<String, String> data = new HashMap();
        data.put("imageData", imageData);
        data.put("sessionId", sessionId);

        //5.响应数据
        return R.ok(data);
    }
}
